package bme.andraskindler.treenventory.db;

import java.util.List;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import bme.andraskindler.treenventory.model.TreeData;

/**
 * Segédosztály, mely a perzisztens műveleteket teszi egyszerűbbé.
 * @author andraskindler
 *
 */
public class TreeStorage {

	private static final Object deleteUpdateLock = new Object();

	private static MongoOperations mongoOperation;

	public TreeStorage() {
		@SuppressWarnings("resource")
		ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
		mongoOperation = (MongoOperations) ctx.getBean("mongoTemplate");
	}

	/**
	 * ID alapú törlés. Ha id == -1, az összes {@link TreeData} típusú objektum törlésre kerül.
	 * @param id
	 */
	public void delete(long id) {
		synchronized (deleteUpdateLock) {
			if (id == -1)
				mongoOperation.remove(new Query(),TreeData.class);
			final Query query = new Query(Criteria.where("id").is(id));
			mongoOperation.remove(query, TreeData.class);
		}
	}

	/**
	 * {@link TreeData} típus mentése.
	 * @param tree
	 */
	public void add(TreeData tree) {
		TreeData copy = copyTree(tree);
		mongoOperation.save(copy);
	}

	/**
	 * Az összes {@link TreeData} példány visszaadása.
	 * @return
	 */
	public List<TreeData> getAll() {
		return mongoOperation.findAll(TreeData.class);
	}

	/**
	 * {@link TreeData} példány módosítása.
	 * @param tree
	 */
	public void update(TreeData tree) {
		TreeData copy = copyTree(tree);

		synchronized (deleteUpdateLock) {

			final Query query = new Query(Criteria.where("id").is(copy.getId()));
			final Update update= new Update();
			update.set("type", copy.getType());
			update.set("latitude", copy.getLatitude());
			update.set("longitude", copy.getLongitude());
			update.set("width", copy.getWidth());
			update.set("date", copy.getDate());
			mongoOperation.findAndModify(query, update, TreeData.class);
		}
	}

	/**
	 * segédfüggvény, mely fát másol.
	 * @param old
	 * @return
	 */
	private TreeData copyTree(TreeData old) {
		TreeData newTree = new TreeData();
		newTree.setId(old.getId());
		newTree.setLatitude(old.getLatitude());
		newTree.setLongitude(old.getLongitude());
		newTree.setType(old.getType());
		newTree.setWidth(old.getWidth());
		newTree.setDate(old.getDate());
		return newTree;
	}
}
